package com.lablabla.parkme;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;
import com.readystatesoftware.mapviewballoons.BalloonItemizedOverlay;

public class PinsOverlay extends BalloonItemizedOverlay<OverlayItem> {
	private Context mContext;
	private ArrayList<OverlayItem> parkingSpaces = new ArrayList<OverlayItem>();
	private Location currentLocation;
	private MapView mapView;
	private Location destinationToReturn = null;
	private ParkMeActivity mainActivity;

	public PinsOverlay(Drawable defaultMarker, MapView mapView, ParkMeActivity mainActivity) {
		super(boundCenter(defaultMarker), mapView);
		this.mainActivity = mainActivity;
		boundCenter(defaultMarker);
		mContext = mapView.getContext();
		this.mapView = mapView;
	}

	@Override
	protected OverlayItem createItem(int i) {
		return parkingSpaces.get(i);
	}

	@Override
	public int size() {
		return parkingSpaces.size();
	}

	public void addOverlay(OverlayItem overlay) {
		parkingSpaces.add(overlay);
		populate();
	}

	static public Location convertGpToLoc(GeoPoint gp) {
		Location convertedLocation = new Location("");
		convertedLocation.setLatitude(gp.getLatitudeE6() / 1e6);
		convertedLocation.setLongitude(gp.getLongitudeE6() / 1e6);
		return convertedLocation;
	}
	
	@Override
	protected boolean onBalloonTap(int index, OverlayItem item) {
		String tmp = parkingSpaces.get(index).getTitle();
		GeoPoint parkingSpace = parkingSpaces.get(index).getPoint();
		Location tmpLoc = convertGpToLoc(parkingSpace);
		double distance = ((currentLocation).distanceTo(tmpLoc));
		DecimalFormat df = new DecimalFormat("#.##");
		tmp = tmp + " is " + String.valueOf(df.format(distance)) + " meters away.";
		Toast.makeText(mContext, tmp, Toast.LENGTH_LONG).show();
		Location destination = convertGpToLoc(parkingSpace);
		getAndDrawDirections(currentLocation, destination);
		Message destinationMessage = new Message();
		Bundle locationData = new Bundle();
		locationData.putParcelable("destination", destination);
		destinationMessage.setData(locationData);
		mainActivity.listeningHandler.sendMessage(destinationMessage);
		hideAllBalloons();
		return true;
	}
	
	public Location getDestination() {
		return destinationToReturn;
	}

	private String getAndDrawDirections(Location currentLocation, Location destination) {
		destinationToReturn = destination;
		boolean sensor = true;
		String result = null;
		try {
			HttpClient httpclient = new DefaultHttpClient();
			
			String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" +
			currentLocation.getLatitude() + "," + currentLocation.getLongitude() + 
			"&destination=" + destination.getLatitude() + "," + destination.getLongitude() + 
			"&sensor=" + sensor ;
			
			HttpPost httppost = new HttpPost(url);
			HttpResponse response = httpclient.execute(httppost);
			HttpEntity entity = response.getEntity();
			InputStream is = null;
			is = entity.getContent();
			BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);

			StringBuilder sb = new StringBuilder();
			sb.append(reader.readLine() + "\n");
			String line = "0";

			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			reader.close();
			result = sb.toString();
			JSONObject jsonObject = new JSONObject(result);
			JSONArray routeArray = jsonObject.getJSONArray("routes");
			JSONObject routes = routeArray.getJSONObject(0);
			JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
			String encodedString = overviewPolylines.getString("points");
			List<GeoPoint> pointToDraw = decodePoly(encodedString);
			mapView.getOverlays().add(new RoutePathOverlay(pointToDraw));
			ParkMeActivity.isRouteDisplayed = true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	public void setCurrentLocation(Location newLocation) {
		currentLocation = newLocation;
	}

	private List<GeoPoint> decodePoly(String encoded) {

		List<GeoPoint> poly = new ArrayList<GeoPoint>();
		int index = 0, len = encoded.length();
		int lat = 0, lng = 0;

		while (index < len) {
			int b, shift = 0, result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lat += dlat;

			shift = 0;
			result = 0;
			do {
				b = encoded.charAt(index++) - 63;
				result |= (b & 0x1f) << shift;
				shift += 5;
			} while (b >= 0x20);
			int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
			lng += dlng;

			GeoPoint p = new GeoPoint((int) (((double) lat / 1E5) * 1E6), (int) (((double) lng / 1E5) * 1E6));
			poly.add(p);
		}

		return poly;
	}
}
